package com.zhumo.sz.provider;

import com.google.common.base.CaseFormat;
import com.zhumo.sz.common.annotation.AlwaysAttribute;
import com.zhumo.sz.common.annotation.NestedEntity;
import com.zhumo.sz.common.annotation.TransientSink;
import com.zhumo.sz.entity.bike.SharedBikeOrderDetail;
import com.zhumo.sz.entity.subway.SubwayStationInfo;
import org.checkerframework.checker.units.qual.C;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author jiaqi.zhu
 * @comment 针对于复杂实体的批量写入Mysql的Provider 可以处理对应属性和嵌套bean 使用Provider 的 前提是Java bean 必须和 MySQL 字段满足驼峰转换关系
 * 嵌套实体只能处理一层
 */
public class BatchNestCorrespondentProvider {

    public <T> String batchInsert(Map<String, List<T>> map) {
        List<T> list = map.get("list");
        StringBuilder sqlBuilder = new StringBuilder("insert into ");
        sqlBuilder.append(getTableName(list.get(0))).append(" (");
        for (Field field : list.get(0).getClass().getDeclaredFields()) {
            field.setAccessible(true);
            TransientSink annotation = field.getAnnotation(TransientSink.class);
            if (annotation == null) {
                if (field.getAnnotation(NestedEntity.class) != null) {
                    //嵌套属性值作为字段值
                    Class<?> nestedClass = field.getType();
                    for (Field nestedField : nestedClass.getDeclaredFields()) {

                        nestedField.setAccessible(true);
                        AlwaysAttribute alwaysAttribute = field.getAnnotation(AlwaysAttribute.class);
                        if (alwaysAttribute != null){
                            String value = alwaysAttribute.value();
                            String nestedFieldName = nestedField.getName();
                            //将原属性首字母转为大写
                            String alwaysFieldName = value + nestedFieldName.substring(0,1).toUpperCase() + nestedFieldName.substring(1);
                            sqlBuilder.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE,alwaysFieldName)).append(",");
                        }else {
                            sqlBuilder.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, nestedField.getName())).append(",");
                        }
                    }
                }else { //普通属性需要增加前缀
                    AlwaysAttribute alwaysAttribute = field.getAnnotation(AlwaysAttribute.class);
                    if (alwaysAttribute != null) {
                        String attributeValue = alwaysAttribute.value();
                        String alwaysFieldName = attributeValue + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1);
                        sqlBuilder.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE,alwaysFieldName)).append(",");
                    } else { //属性和字段名完全对应
                        sqlBuilder.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName())).append(",");
                    }
                }
            }
        }
        sqlBuilder.deleteCharAt(sqlBuilder.length()-1).append(") values ");
        Field[] fields = list.get(0).getClass().getDeclaredFields();
        for (int i = 0; i < list.size(); i++) {
            sqlBuilder.append("(");
            for (Field field : fields) {
                field.setAccessible(true);
                if (field.getAnnotation(TransientSink.class) == null) {
                    //todo 判断嵌套bean
                    String fieldName = field.getName();
                    if (field.getAnnotation(NestedEntity.class) != null){
                        Class<?> fieldClass = field.getType();
                        Field[] nestedEntityFieldList = fieldClass.getDeclaredFields();
                        for (Field nestedField : nestedEntityFieldList) {
                            nestedField.setAccessible(true);
                            String nestedFieldName = nestedField.getName();
                            sqlBuilder.append("#{list[" + i + "]." + fieldName + "." + nestedFieldName + "},");
                        }
                    }else { //字段名为属性名
                        String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); //获取get方法名
                        sqlBuilder.append("#{list[" + i + "]." + fieldName + "},"); //直接.属性
                    }
                }
            }
            sqlBuilder.deleteCharAt(sqlBuilder.length()-1);
            sqlBuilder.append("),");
        }
        sqlBuilder.deleteCharAt(sqlBuilder.length() - 1); // 去掉最后一个逗号
        return sqlBuilder.toString();
    }

    /**
     * 获取表名
     * @param t 插入实体类型
     * @param <T> 泛型
     * @return insert sql
     */
    private <T> String getTableName(T t) {
        Class<?> tClass = t.getClass();
        return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE,tClass.getSimpleName());
    }

    /**
     * 拼接value 占位符
     * @param t
     * @param <T>
     * @return
     */
    private <T> String getValuesIndex(T t){
        StringBuilder valueBuilder = new StringBuilder("(");
        Class<?> tClass = t.getClass();
        Field[] fields = tClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            if (field.getAnnotation(TransientSink.class) == null){
                valueBuilder.append("#{").append(field.getName()).append("},");
            }
        }
        valueBuilder.deleteCharAt(valueBuilder.length()-1).append(")"); //去掉最后一个逗号
        return valueBuilder.toString();
    }

    public static void main(String[] args) {
        BatchNestCorrespondentProvider batchInsertProvider = new BatchNestCorrespondentProvider();
        ArrayList<SharedBikeOrderDetail> bikeOrderDetails = new ArrayList<>();
        for (int i = 0; i < 1; i++) {
            bikeOrderDetails.add(new SharedBikeOrderDetail());
        }
        HashMap<String, List<SharedBikeOrderDetail>> stringListHashMap = new HashMap<>();
        stringListHashMap.put("list",bikeOrderDetails);
        System.out.println(batchInsertProvider.batchInsert(stringListHashMap));
    }
    /*
    insert into subway_station_info columns (id,line_code,line_name,site_name,site_code,oper_code,site_introduced)
    values (#{id},#{lineCode},#{lineName},#{siteName},#{siteCode},#{operCode},#{siteIntroduced})
     */
}
